﻿using System.Windows.Input;
using Com.JJ1369.Infrastructure.ViewModel;
using Com.JJ1369.HumanResource.Department.Interface;
using Com.JJ1369.Service.Service;
using Com.JJ1369.Service.Model;
using System.ServiceModel.DomainServices.Client;
using System.ComponentModel.Composition;
using Microsoft.Practices.Prism.Commands;
using System.ComponentModel;
using System.Windows;
using System.Linq;
using Microsoft.Windows.Data.DomainServices;
using System.Collections.Specialized;
using Microsoft.Practices.Prism.Regions;

namespace Com.JJ1369.HumanResource.Department.ViewModel
{
    [Export(typeof(IDepartmentTypeViewModel))]
    [PartCreationPolicy(System.ComponentModel.Composition.CreationPolicy.NonShared)]
    public class DepartmentTypeViewModel:ViewModelBase, IDepartmentTypeViewModel
    {
        
        private readonly DepartmentTypeContext _DomainContext;
        private readonly EntityList<DepartmentType> _Source;
        private readonly DomainCollectionViewLoader<DepartmentType> _Loader;
        private readonly DomainCollectionView<DepartmentType> _View;
        private const string _LoadingString = "Loading......";
        private const string _SubmitString = "Submitting......";
        private const string EditViewUri="DepartmentTypeEditView";
        private IRegionManager _RegionManager;

        [ImportingConstructor]
        public DepartmentTypeViewModel(IRegionManager manager)
        {
            this._RegionManager = manager;
            this._DomainContext = new DepartmentTypeContext();
            this._Source = new EntityList<DepartmentType>(_DomainContext.DepartmentTypes);
            this._Loader= new DomainCollectionViewLoader<DepartmentType>(this.LoadDepartmentType,OnLoadDepartmentTypeEntitiesCompleted);
            this._View = new DomainCollectionView<DepartmentType>(_Loader, _Source);
            this._PageSize = 5;
            this._View.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
            INotifyCollectionChanged notifyingSortDescriptions =
                (INotifyCollectionChanged)this.DepartmentTypeList.SortDescriptions;
            notifyingSortDescriptions.CollectionChanged +=
                (sender, e) => this._View.MoveToFirstPage();

            using (this.DepartmentTypeList.DeferRefresh())
            {
                this._View.PageSize = _PageSize;
                this._View.MoveToFirstPage();
            }

            this._AddCommand = new DelegateCommand(this.Add, this.CanAdd);
            this._DeleteCommand = new DelegateCommand(this.Delete, this.CanDelete);
            this._SaveCommand = new DelegateCommand(this.Save, this.CanSave);
            DepartmentTypeList.CurrentChanged += new System.EventHandler(_DepartmentTypeList_CurrentChanged);
            NewItem = new DepartmentType();
        }



        private LoadOperation<DepartmentType> LoadDepartmentType()
        {
            BusyContent = _LoadingString;
            RaisePropertyChanged(() => this.IsBusy);
            EntityQuery<DepartmentType> query = this._DomainContext.GetDepartmentTypeListQuery();
            query = query.SortAndPageBy(_View);
            query.IncludeTotalCount=true;
            return this._DomainContext.Load<DepartmentType>(query);

        }

        private void OnLoadDepartmentTypeEntitiesCompleted(LoadOperation<DepartmentType> op)
        {
            RaisePropertyChanged(() => this.IsBusy);
            if (op.HasError)
            {
                MessageBox.Show(op.Error.Message);
                op.MarkErrorAsHandled();
            }
            else if (!op.IsCanceled)
            {
                if (op.TotalEntityCount != -1)
                {
                    this._View.SetTotalItemCount(op.TotalEntityCount);
                }
                this._Source.Source = op.Entities;
            }
        }

        void _DepartmentTypeList_CurrentChanged(object sender, System.EventArgs e)
        {
            var delegateCommand = _DeleteCommand as DelegateCommand;
            if (delegateCommand != null) delegateCommand.RaiseCanExecuteChanged();
            RaisePropertyChanged(() => this.CanEdit);
            DelegateCommand command = _SaveCommand as DelegateCommand;
            if (command != null) command.RaiseCanExecuteChanged();
            if (_View.CurrentItem == null)
            {
                return;
            }
            (_View.CurrentItem as DepartmentType).PropertyChanged -= new PropertyChangedEventHandler(DepartmentTypeViewModel_PropertyChanged);
            (_View.CurrentItem as DepartmentType).PropertyChanged += new PropertyChangedEventHandler(DepartmentTypeViewModel_PropertyChanged);
        }

        void DepartmentTypeViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            (this.SaveCommand as DelegateCommand).RaiseCanExecuteChanged();
        }


        #region IDepartmentTypeViewModel members

        public ICollectionView DepartmentTypeList
        {
            get
            {
                return _View;
            }
        }


        public bool CanEdit
        {
            get
            {
                return _View.CurrentItem !=null;
            }
        }
        private int _PageSize;
        public int PageSize
        {
            get
            {
                return _PageSize;
            }
            private set
            {
                if (_PageSize != value)
                {
                    _PageSize = value;
                    RaisePropertyChanged(() => this.PageSize);
                }
            }
        }

        private ICommand _AddCommand;
        public ICommand AddCommand
        {
            get
            {
                return _AddCommand;
            }
            set
            {
                if (_AddCommand != value)
                {
                    this._AddCommand = value;
                    RaisePropertyChanged(() => this.AddCommand);
                }
            }
        }

        private DepartmentType _NewItem;
        public DepartmentType NewItem
        {
            get
            {
                return _NewItem;
            }
            set
            {
                _NewItem = value;
                RaisePropertyChanged(() => this.NewItem);
            }
        }

        private ICommand _SaveCommand;
        public ICommand SaveCommand
        {
            get
            {
                return _SaveCommand;
            }
            set
            {
                if (_SaveCommand != value)
                {
                    this._SaveCommand = value;
                    RaisePropertyChanged(() => this.SaveCommand);
                }
            }
        }


        private ICommand _DeleteCommand;
        public ICommand DeleteCommand
        {
            get
            {
                return _DeleteCommand;
            }
            set
            {
                if (_DeleteCommand != value)
                {
                    _DeleteCommand = value;
                    RaisePropertyChanged(() => this.DeleteCommand);
                }
            }
        }


        private string _BusyContent;
        public string BusyContent
        {
            get
            {
                return _BusyContent;
            }
            private set
            {
                if (_BusyContent != value)
                {
                    _BusyContent = value;
                    RaisePropertyChanged(() => this.BusyContent);
                }
            }
        }

        public bool IsBusy
        {
            get
            {
                return _DomainContext.IsLoading || _DomainContext.IsSubmitting;
            }
        }

        #endregion

        private bool CanDelete()
        {
            return DepartmentTypeList.CurrentItem != null ? true : false;
        }

        private void Delete()
        {
            if (DepartmentTypeList.CurrentItem != null)
            {
                _Source.Remove(DepartmentTypeList.CurrentItem as DepartmentType);
                SubmitOperation so = _DomainContext.SubmitChanges();
                BusyContent = _SubmitString;
                RaisePropertyChanged(() => this.IsBusy);
                so.Completed += (s, e) =>
                {
                    RaisePropertyChanged(() => this.IsBusy);
                    using (this.DepartmentTypeList.DeferRefresh())
                    {
                        this._View.PageSize = _PageSize;
                    }
                };
            }
        }

        private bool CanSave()
        {
            if (DepartmentTypeList != null)
            {
                var type = DepartmentTypeList.CurrentItem as DepartmentType;
                return type != null && type.HasChanges && !type.HasValidationErrors;
            }
            return false;
        }

        private void Save()
        {
            _DomainContext.SubmitChanges();
        }

        private bool CanAdd()
        {
            return true;
        }

        private void Add()
        {
            _DomainContext.RejectChanges();
            if (NewItem.HasValidationErrors)
            {
                return;
            }
            _DomainContext.DepartmentTypes.Add(NewItem);
            _DomainContext.SubmitChanges(this.SubmitCallBack, null);
            BusyContent = _SubmitString;
            RaisePropertyChanged(() => this.IsBusy);
        }

        private void SubmitCallBack(SubmitOperation so)
        {
            BusyContent = _SubmitString;
            RaisePropertyChanged(() => this.IsBusy);
            
            if (so.Error != null)
            {
                if (so.EntitiesInError.Any())
                {
                    RaisePropertyChanged(() => this.NewItem);
                }
                else
                {
                    MessageBox.Show(so.Error.Message);
                }
                so.MarkErrorAsHandled();
                return;
            }
            NewItem = new DepartmentType();
            RaisePropertyChanged(()=>this.NewItem);
            this._View.SetTotalItemCount(_Source.Count());
            using (DepartmentTypeList.DeferRefresh())
            {
                this._View.PageSize = _PageSize;
            }
        }
    }
}
